﻿using Irony.Parsing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AppServidor
{
    class CompiladorPista
    {
        String error;
        string ruta_compilacion;
        List<Simbolo> tablaSimbolos;
        int contid;

        public List<Simbolo> TablaSimbolos
        {
            get { return tablaSimbolos; }
            set {tablaSimbolos = value; }
        }
        public string Ruta_compilacion
        {
            get { return ruta_compilacion; }
            set { ruta_compilacion = value; }
        }
        public CompiladorPista() {
            contid = 0;
        tablaSimbolos = new List<Simbolo>();
        }


       public Pista getPista(String source) {
           LanguageData lenguaje = new LanguageData(new GramaticaPista());
           Parser p = new Parser(lenguaje);
           ParseTree arbol = p.Parse(source);
           if (arbol.Root != null)
           {
               Pista pista = new Pista();


               S(arbol.Root, pista);

               return pista;
           }
           return null;
        }

       private void S(ParseTreeNode nodo, Pista objeto) {
         ParseTreeNode p=  nodo.ChildNodes[0];
           String cadena=p.Term.ToString();
           if (cadena.Equals("P"))
           {
               P(p, objeto);

           }
           else { System.Console.WriteLine("aqui paso algo raro  XD"); }
       }

       private void P(ParseTreeNode nodo, Pista objeto)
       { ///aqui viene el nombre de la pista y de las que extiende :)
           ParseTreeNode cabecera = nodo.ChildNodes[0];
           ParseTreeNode cuerpo = nodo.ChildNodes[1];
           Cabecera(cabecera,objeto);
           Cuerpo(cuerpo, objeto);
       }

       private void Cuerpo(ParseTreeNode nodo, Pista objeto) {
           ParseTreeNodeList listacuerpo = nodo.ChildNodes;
           if (listacuerpo.Count > 1)
           {
               ParseTreeNode cuerpop = listacuerpo[0];
               ParseTreeNode spista = listacuerpo[1];

               Cuerpo(cuerpop, objeto);
               Spista(spista,objeto);

           }
           else { 
               ParseTreeNode spista = listacuerpo[0];
               Spista(spista, objeto);
           }
       }

       private void Spista(ParseTreeNode nodo, Pista objeto) {
           String spistanodo = nodo.ToString();

           if (spistanodo.CompareTo("Decla_var_asig") == 0) {
               ParseTreeNodeList list = nodo.ChildNodes;
               object valor = Valor(list[2]);

               decla_var(list[0], objeto, valor,null);

           }
           else if (spistanodo.CompareTo("Decla_var") == 0){
               decla_var(nodo, objeto, null,null);
           }
           else if (spistanodo.CompareTo("Decla_metodos") == 0)
           {
               ParseTreeNodeList list = nodo.ChildNodes;
               decla_metodos(list[0], objeto);
           }
           else if (spistanodo.CompareTo("Decla_array") == 0)
           {
               ParseTreeNodeList list = nodo.ChildNodes;
               decla_array(list[0], objeto, null);
           }
           else if (spistanodo.CompareTo("Decla_array_asig") == 0)
           {
               ParseTreeNodeList list = nodo.ChildNodes;
               decla_array_asig(list[0], objeto);
           }
           else if (spistanodo.CompareTo("Asignacion") == 0)
           {
               Asignacion(nodo);
           }
       }

       private object AsigSimplificada(ParseTreeNode nodo) {
           ParseTreeNodeList list = nodo.ChildNodes;

           if (list[0].FindTokenAndGetText().CompareTo("++") == 0) {
               Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Contains(list[1].FindTokenAndGetText()));
               if (temp.TipoSim.CompareTo("variable") == 0) {
                   double t1 = Convert.ToDouble(temp.Valor);
                     return  temp.Valor = t1 + 1;
               }
           }
           else if (list[1].FindTokenAndGetText().CompareTo("++") == 0)
           {
               Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Contains(list[0].FindTokenAndGetText()));
               if (temp.TipoSim.CompareTo("variable") == 0) {
                   double t1 = Convert.ToDouble(temp.Valor);
                   temp.Valor = t1 + 1;
                   return t1;
               }
           }
           else if (list[0].FindTokenAndGetText().CompareTo("--") == 0)
           {
               Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Contains(list[1].FindTokenAndGetText()));
               if (temp.TipoSim.CompareTo("variable") == 0) {
                   double t1 = Convert.ToDouble(temp.Valor);
                   return temp.Valor = t1 - 1;
               }
           }
           else if (list[1].FindTokenAndGetText().CompareTo("--") == 0)
           {
               Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Contains(list[0].FindTokenAndGetText()));
               if (temp.TipoSim.CompareTo("variable") == 0) {
                   double t1 = Convert.ToDouble(temp.Valor);
                   temp.Valor = t1 - 1;
                   return t1;
               }
           }
           return null;
       }

       private void decla_metodos(ParseTreeNode nodo, Pista objeto)
       {
           ParseTreeNodeList list = nodo.ChildNodes;
           if (list[0].FindTokenAndGetText().CompareTo("Principal") == 0)
           {
               //metodo principal
               Simbolo meth = new Simbolo(contid, "Principal", "metodo", "", "", "global", objeto.Nombre, false);
               contid++;
               tablaSimbolos.Add(meth);
               meth.Morf = list[1];
               LS(list[1], list[0].FindTokenAndGetText());
           }
           else if (list[0].FindTokenAndGetText().CompareTo("Keep") == 0)
           {
               if (list[1].ToString().CompareTo("Tipo") == 0)
               {
                   ParseTreeNodeList hijo = list[1].ChildNodes;
                   Simbolo meth = new Simbolo(contid, list[2].FindTokenAndGetText(), "metodo", hijo[0].FindTokenAndGetText(), "", "global", objeto.Nombre, true);
                   contid++;
                   tablaSimbolos.Add(meth);
                   if (list.Count < 5)
                   {
                       //metodo keep sin parametros
                       meth.Morf = list[3];
                       LS(list[3], list[2].FindTokenAndGetText());
                   }
                   else
                   {
                       //metodo keep con parametros
                       meth.Morf = list[4];
                       LDP(list[3], list[2].FindTokenAndGetText());
                       LS(list[4], list[2].FindTokenAndGetText());
                   }
               }
               else
               {
                   Simbolo meth = new Simbolo(contid, list[1].FindTokenAndGetText(), "metodo", "", "", "global", objeto.Nombre, true);
                   contid++;
                   tablaSimbolos.Add(meth);
                   if (list.Count < 4)
                   {
                       //metodo keep sin parametros
                       meth.Morf = list[2];
                       LS(list[2], list[1].FindTokenAndGetText());
                   }
                   else
                   {
                       //metodo keep con parametros
                       meth.Morf = list[3];
                       LDP(list[2], list[1].FindTokenAndGetText());
                       LS(list[3], list[1].FindTokenAndGetText());
                   }
               }
           }
           else
           {
               if (list[0].ToString().CompareTo("Tipo") == 0)
               {
                   ParseTreeNodeList hijo = list[0].ChildNodes;
                   Simbolo meth = new Simbolo(contid, list[1].FindTokenAndGetText(), "metodo", hijo[0].FindTokenAndGetText(), "", "global", objeto.Nombre, false);
                   contid++;
                   tablaSimbolos.Add(meth);
                   if (list.Count < 4)
                   {
                       //metodo sin parametros
                       meth.Morf = list[2];
                       LS(list[2], list[1].FindTokenAndGetText());
                   }
                   else
                   {
                       //metodo con parametros
                       meth.Morf = list[3];
                       LDP(list[2], list[1].FindTokenAndGetText());
                       LS(list[3], list[1].FindTokenAndGetText());
                   }
               }
               else 
               {
                   Simbolo meth = new Simbolo(contid, list[0].FindTokenAndGetText(), "metodo", "", "", "global", objeto.Nombre, false);
                   contid++;
                   tablaSimbolos.Add(meth);
                   if (list.Count < 4)
                   {
                       //metodo sin parametros
                       meth.Morf = list[1];
                       LS(list[1], list[0].FindTokenAndGetText());
                   }
                   else
                   {
                       //metodo con parametros
                       meth.Morf = list[2];
                       LDP(list[1], list[0].FindTokenAndGetText());
                       LS(list[2], list[0].FindTokenAndGetText());
                   }
               }
           }
       }

       private object LS(ParseTreeNode nodo, String padre) {
           ParseTreeNodeList list = nodo.ChildNodes;
           ParseTreeNodeList tlist = list[1].ChildNodes;
           object r = null;
           if (list.Count == 2)
           {
               string isOut = Convert.ToString(LS(list[0], padre));
               if (isOut.CompareTo("isOut")==0) {
                   r = "isOut";
               }
               else
               {
                   object t = Sent(list[1], padre);
                   if (tlist[1].FindTokenAndGetText().CompareTo("retorno") == 0 || tlist[1].FindTokenAndGetText().CompareTo("salir") == 0)
                   {
                       r = t;
                   }
               }
           }
           else {
              object t = Sent(list[0], padre);
              if (tlist[1].FindTokenAndGetText().CompareTo("retorno") == 0) {
                  r = t;
              }
           }
           return r;
       }

       private object Sent(ParseTreeNode nodo1, String padre) {
           ParseTreeNodeList list_ = nodo1.ChildNodes;
           ParseTreeNode nodo = list_[0];
           String spistanodo = nodo.ToString();
           object r = null;
           if (spistanodo.CompareTo("Decla_var_asig") == 0)
           {
               ParseTreeNodeList list = nodo.ChildNodes;
               object valor = Valor(list[2]);

               decla_var_local(list[0], padre, valor,null);

           }
           else if (spistanodo.CompareTo("Decla_var") == 0)
           {
               decla_var_local(nodo, padre, "",null);
           }
           else if (spistanodo.CompareTo("Decla_array") == 0)
           {
               decla_array_local(nodo, padre, null);
           }
           else if (spistanodo.CompareTo("Decla_array_asig") == 0)
           {
               decla_array_asig_local(nodo, padre);
           }
           else if (spistanodo.CompareTo("Asignacion") == 0)
           {
               Asignacion(nodo);
           }
           else if (spistanodo.CompareTo("doWhile_") == 0)
           {
               doWhile_(nodo, padre);
           }
           else if (spistanodo.CompareTo("If_") == 0)
           {
               If_(nodo, padre);
           }
           else if (spistanodo.CompareTo("Switch_") == 0)
           {
               Switch_(nodo, padre);
           }
           else if (spistanodo.CompareTo("For_") == 0)
           {
               For_(nodo, padre);
           }
           else if (spistanodo.CompareTo("While_") == 0)
           {
               While_(nodo, padre);
           }
           else if (spistanodo.CompareTo("CallMorF") == 0)
           {
               CallMorF(nodo);
           }
           else if (spistanodo.CompareTo("salir") == 0)
           {
               r = "isOut";
           }
           else if (spistanodo.CompareTo("retorna") == 0)
           {
               r = Valor(list_[1]);
           }
           return r;
       }

       private void Asignacion(ParseTreeNode nodo) {
           ParseTreeNodeList list = nodo.ChildNodes;
           if (list[1].FindTokenAndGetText().CompareTo("=") == 0)
           {
               Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Equals(list[0].FindTokenAndGetText()));
               if (temp.TipoSim.CompareTo("variable") == 0)
               {
                   String temptipo = temp.TipoDato;
                   object tv =  Valor(list[2]);

                   object valor = casteo(temptipo,tv.GetType(),tv);
                   if (valor != null)
                   {
                       temp.Valor = tv;
                   }
                   else { 
                   //error de casteo
                   }
               }
           }
           else if (list[1].FindTokenAndGetText().CompareTo("+=") == 0)
           {
               Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Equals(list[0].FindTokenAndGetText()));
               if (temp.TipoSim.CompareTo("variable") == 0)
               {
                   String ts1 = temp.Valor.ToString();
                   String ts2 = Valor(list[2]).ToString();
                   double t1;
                   double t2;
                   bool tr1 = Double.TryParse(ts1, out t1);
                   bool tr2 = Double.TryParse(ts2, out t2);

                   if (tr1 == true && tr2 == true)
                   {
                       temp.Valor = t1 + t2;
                   }
                   else
                   {
                       temp.Valor = ts1 + ts2;
                   }
               }
           }
           else if (list[0].ToString().CompareTo("AsigSimplificada") == 0)
           {
               AsigSimplificada(list[0]);
           }
           else if (list[2].FindTokenAndGetText().CompareTo("=") == 0)
           {
               Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Equals(list[0].FindTokenAndGetText()));
               if (temp.TipoSim.CompareTo("arreglo") == 0)
               {
                   object[] arr = (object[])temp.Valor;
                   List<int> dimensiones = temp.Dims;
                   List<int> indice = new List<int>();
                   dims(list[1], indice);

                   int pos = indice[0] - 1;
                   if (dimensiones.Count > 1)
                   {
                       int w = 1;
                       while (w < dimensiones.Count)
                       {
                           pos = (pos * dimensiones[w]) + (indice[w] - 1);
                           w++;
                       }
                   }
                   arr[pos] = Valor(list[3]);
               }
           }
       }

       private object casteo(string tipovar, Type tipoval, object valor) {
           object r = null;

            if (tipovar.CompareTo("entero") == 0) 
           {
               if (tipoval == typeof(int)) 
               {
                   r = valor;
               }
               else if (tipoval == typeof(bool))
               {
                   r = Convert.ToUInt32(valor);
               }
               else if (tipoval == typeof(double))
               {
                   r = Convert.ToUInt32(valor);
               }
               else if (tipoval == typeof(char))
               {
                   string s =Convert.ToString(valor);
                   r = Encoding.ASCII.GetBytes(s)[0];
               }
           }
           else if (tipovar.CompareTo("cadena") == 0)
           {
               r = Convert.ToString(valor);
           }
           else if (tipovar.CompareTo("boolean") == 0)
           {
               if (tipoval == typeof(bool))
               {
                   r = valor;
               }
           }
           else if (tipovar.CompareTo("doble") == 0)
           {
               if (tipoval == typeof(int))
               {
                   r = Convert.ToDouble(valor);
               }
               else if (tipoval == typeof(double))
               {
                   r = valor;
               }
           }
           else if (tipovar.CompareTo("caracter") == 0)
           {
               if (tipoval == typeof(int))
               {
                   r = Convert.ToChar(valor);
               }
               else if (tipoval == typeof(char))
               {
                   r = valor;
               }
           }
           return r;
       }

       private void LDP(ParseTreeNode nodo, String padre) {
           ParseTreeNodeList list = nodo.ChildNodes;
           if (list.Count == 2)
           {
               ParseTreeNodeList hijo = list[0].ChildNodes;
               Simbolo varmeth = new Simbolo(contid, list[1].FindTokenAndGetText(), "parametro", hijo[0].FindTokenAndGetText(), "", "local", padre, false);
               contid++;
               tablaSimbolos.Add(varmeth);
           }
           else {
               LDP(list[0], padre);

               ParseTreeNodeList hijo = list[1].ChildNodes;
               Simbolo varmeth = new Simbolo(contid, list[2].FindTokenAndGetText(), "parametro", hijo[0].FindTokenAndGetText(), "", "local", padre, false);
               contid++;
               tablaSimbolos.Add(varmeth);
           }
       }

       private String decla_var(ParseTreeNode nodo, Pista objeto, Object val, List<int> dim) {
           ParseTreeNodeList list = nodo.ChildNodes;
          
           if (list.Count == 2)
           {
               String infovar = decla_var(list[0], objeto,val,dim);
               string[] words = infovar.Split(',');
               String tipovar = words[0];
               String tkeep = words[1];
               string tarray = words[2];
               Simbolo var;
               if (tkeep.CompareTo("keep") == 0)
               {
                   if (tarray.CompareTo("arreglo") == 0)
                   {
                       var = new Simbolo(contid, list[1].FindTokenAndGetText(), "arreglo", tipovar, val, "global", objeto.Nombre, true);
                       var.Dims = dim;
                   }
                   else
                   {
                       var = new Simbolo(contid, list[1].FindTokenAndGetText(), "variable", tipovar, val, "global", objeto.Nombre, true);
                   }
               }
               else
               {
                   if (tarray.CompareTo("arreglo") == 0)
                   {
                       var = new Simbolo(contid, list[1].FindTokenAndGetText(), "arreglo", tipovar, val, "global", objeto.Nombre, false);
                       var.Dims = dim;
                   }
                   else
                   {
                       var = new Simbolo(contid, list[1].FindTokenAndGetText(), "variable", tipovar, val, "global", objeto.Nombre, false);
                   }
               }
               contid++;
               tablaSimbolos.Add(var);

               return infovar;
           }
           else if(list.Count == 3){
               ParseTreeNode hijo = list[1];
               String tipovar = hijo.ChildNodes[0].FindTokenAndGetText();
               Simbolo var = new Simbolo(contid,list[2].FindTokenAndGetText(),"variable",tipovar,val,"global",objeto.Nombre,false);
               contid++;
               tablaSimbolos.Add(var);

               return tipovar+", , ";
           }
           else if (list.Count == 4)
           {
               if (list[0].FindTokenAndGetText().CompareTo("Keep") == 0) { 
                ParseTreeNode hijo = list[2];
                String tipovar = hijo.ChildNodes[0].FindTokenAndGetText();
                Simbolo var = new Simbolo(contid, list[3].FindTokenAndGetText(), "variable", tipovar, val, "global", objeto.Nombre,true);
                contid++;
                tablaSimbolos.Add(var);

                return tipovar+",keep, ";
               }else{

                ParseTreeNode hijo = list[1];
                String tipovar = hijo.ChildNodes[0].FindTokenAndGetText();
                Simbolo var = new Simbolo(contid, list[3].FindTokenAndGetText(), "arreglo", tipovar, val, "global", objeto.Nombre,false);
                contid++;
                tablaSimbolos.Add(var);
                var.Dims = dim;

                return tipovar + ", ,arreglo";
               }
           }
           else if (list.Count == 5)
           {
                   ParseTreeNode hijo = list[2];
                   String tipovar = hijo.ChildNodes[0].FindTokenAndGetText();
                   Simbolo var = new Simbolo(contid, list[4].FindTokenAndGetText(), "arreglo", tipovar, val, "global", objeto.Nombre, true);
                   contid++;
                   tablaSimbolos.Add(var);
                   var.Dims = dim;

                   return tipovar+",keep,arreglo";
           }
           return "";
       }

       private String decla_var_local(ParseTreeNode nodo, String objeto, Object val, List<int> dim)
       {
           ParseTreeNodeList list = nodo.ChildNodes;

           if (list.Count == 2)
           {
               String infovar = decla_var_local(list[0], objeto, val, dim);
               string[] words = infovar.Split(',');
               String tipovar = words[0];
               String tkeep = words[1];
               string tarray = words[2];
               Simbolo var;
               if (tkeep.CompareTo("keep") == 0)
               {
                   if (tarray.CompareTo("arreglo") == 0)
                   {
                       var = new Simbolo(contid, list[1].FindTokenAndGetText(), "arreglo", tipovar, val, "local", objeto, true);
                       var.Dims = dim;
                   }
                   else
                   {
                       var = new Simbolo(contid, list[1].FindTokenAndGetText(), "variable", tipovar, val, "local", objeto, true);
                   }
               }
               else
               {
                   if (tarray.CompareTo("arreglo") == 0)
                   {
                       var = new Simbolo(contid, list[1].FindTokenAndGetText(), "arreglo", tipovar, val, "local", objeto, false);
                       var.Dims = dim;
                   }
                   else
                   {
                       var = new Simbolo(contid, list[1].FindTokenAndGetText(), "variable", tipovar, val, "local", objeto, false);
                   }
               }
               contid++;
               tablaSimbolos.Add(var);

               return infovar;
           }
           else if (list.Count == 3)
           {
               ParseTreeNode hijo = list[1];
               String tipovar = hijo.ChildNodes[0].FindTokenAndGetText();
               Simbolo var = new Simbolo(contid, list[2].FindTokenAndGetText(), "variable", tipovar, val, "local", objeto, false);
               contid++;
               tablaSimbolos.Add(var);

               return tipovar + ", , ";
           }
           else if (list.Count == 4)
           {
               if (list[0].FindTokenAndGetText().CompareTo("Keep") == 0)
               {
                   ParseTreeNode hijo = list[2];
                   String tipovar = hijo.ChildNodes[0].FindTokenAndGetText();
                   Simbolo var = new Simbolo(contid, list[3].FindTokenAndGetText(), "variable", tipovar, val, "local", objeto, true);
                   contid++;
                   tablaSimbolos.Add(var);

                   return tipovar + ",keep, ";
               }
               else
               {

                   ParseTreeNode hijo = list[1];
                   String tipovar = hijo.ChildNodes[0].FindTokenAndGetText();
                   Simbolo var = new Simbolo(contid, list[3].FindTokenAndGetText(), "arreglo", tipovar, val, "local", objeto, false);
                   contid++;
                   tablaSimbolos.Add(var);
                   var.Dims = dim;

                   return tipovar + ", ,arreglo";
               }
           }
           else if (list.Count == 5)
           {
               ParseTreeNode hijo = list[2];
               String tipovar = hijo.ChildNodes[0].FindTokenAndGetText();
               Simbolo var = new Simbolo(contid, list[4].FindTokenAndGetText(), "arreglo", tipovar, val, "local", objeto, true);
               contid++;
               tablaSimbolos.Add(var);
               var.Dims = dim;

               return tipovar + ",keep,arreglo";
           }
           return "";
       }

       private void decla_array(ParseTreeNode nodo, Pista objeto, List<object> val) {
           ParseTreeNodeList list = nodo.ChildNodes;
           
           List<int> dimensiones = new List<int>();
           dims(list[1], dimensiones);
           int ndims = 0;
           int i;
           for (i = 0; i < dimensiones.Count; i++)
           {
               if (ndims == 0)
               {
                   ndims = dimensiones[i];
               }
               ndims = ndims * dimensiones[i];
           }

           Object[] arr = new object[ndims];
           if (val != null) {
               asignarValoresArray(val, dimensiones, ndims, arr);
           }

           decla_var(list[0], objeto, arr, dimensiones);
       }

       public void asignarValoresArray(List<object> val,List<int> dimensiones, int ndims,Object[] arr) {
         
               // 0 dim j, 1 dim i
               int[] indice = new int[dimensiones.Count];
               for (int g = 0; g < dimensiones.Count; g++)
               {
                   indice[g] = 1;
               }

               if (val.Count == ndims)
               {
                   int j;
                   for (j = 0; j < ndims; j++)
                   {
                       int pos = indice[0] - 1;
                   if (dimensiones.Count > 1)
                   {
                       int w = 1;
                       while (w < dimensiones.Count)
                       {
                           pos = (pos * dimensiones[w]) + (indice[w] - 1);
                           sumarDimension(indice, dimensiones, w);
                           w++;
                       }
                   }
                   else {
                       sumarDimension(indice, dimensiones, 0);
                   }
                       arr[pos] = val[j];
                       System.Console.WriteLine(pos + " " + val[j]);
                   }
               }
               else
               {
                   //error falta de datos
               }
       }

       public void sumarDimension(int[] indices, List<int> tamdim, int i) {

           if (indices[i] < tamdim[i])
           {
               indices[i] = indices[i] + 1;
           }
           else {
               indices[i] = 1;
               sumarDimension(indices, tamdim, i+1);
           }
       }

       private void decla_array_local(ParseTreeNode nodo, String objeto, object val) {
           ParseTreeNodeList list = nodo.ChildNodes;

           List<int> dimensiones = new List<int>();
           dims(list[1], dimensiones);
           int ndims=0;
           int i;
           for (i = 0; i < dimensiones.Count; i++) { 
           if(ndims == 0){
               ndims = dimensiones[i];
           }
           ndims = ndims * dimensiones[i];
           }
           Object[] arr= new object[ndims];
           decla_var_local(list[0], objeto, arr,dimensiones);
    }

       private void dims(ParseTreeNode nodo, List<int> tamdim) {
           ParseTreeNodeList list = nodo.ChildNodes;

           if (list.Count == 2)
           {
               dims(list[0], tamdim);
               tamdim.Add(Convert.ToInt32(list[1]));
           }
           else {
               tamdim.Add(Convert.ToInt32(list[0]));
           }
       }

       private void decla_array_asig(ParseTreeNode nodo, Pista objeto) {
           ParseTreeNodeList list = nodo.ChildNodes;
           List<object> listval = new List<object>();
           LE(list[1], listval);
           decla_array(list[0],objeto,listval);
       }

       private void decla_array_asig_local(ParseTreeNode nodo, string objeto)
       {
           ParseTreeNodeList list = nodo.ChildNodes;
           List<object> listval = new List<object>();
           LE(list[1], listval);
           decla_array_local(list[0], objeto, listval);
       }

       private void LE(ParseTreeNode nodo, List<object> listval)
       {
           ParseTreeNodeList list = nodo.ChildNodes;

           if (list[0].ToString().CompareTo("LE") == 0)
           {
               if (list[1].ToString().CompareTo("E") == 0) {
                   LE(list[0], listval);
                   listval.Add(E(list[0]));
               }
               else if (list[1].ToString().CompareTo("LE") == 0)
               {
                   LE(list[0], listval);
                   LE(list[1], listval);
               }
               else {
                   LE(list[0],listval);
               }
           }
           else {
               listval.Add(E(list[0]));
           }
       }

       private object E(ParseTreeNode nodo){
           ParseTreeNodeList list = nodo.ChildNodes;
           object r= null;
           if (list[1].FindTokenAndGetText().CompareTo("+") == 0)
           {
               String ts1 = E(list[0]).ToString();
               String ts2 = E(list[2]).ToString();
               double t1;
               double t2;
               bool tr1 = Double.TryParse(ts1, out t1);
               bool tr2 = Double.TryParse(ts2, out t2);

               if (tr1 == true && tr2 == true)
               {
                   r = t1 + t2;
               }
               else {
                   r = ts1 + ts2;
               }
               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("-") == 0)
           {
               Double t1 = Convert.ToDouble(E(list[0]));
               Double t2 = Convert.ToDouble(E(list[2]));

               r = t1 - t2;

               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("*") == 0)
           {
               Double t1 = Convert.ToDouble(E(list[0]));
               Double t2 = Convert.ToDouble(E(list[2]));

               r = t1 * t2;

               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("/") == 0)
           {
               Double t1 = Convert.ToDouble(E(list[0]));
               Double t2 = Convert.ToDouble(E(list[2]));

               r = t1 / t2;

               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("%") == 0)
           {
               Double t1 = Convert.ToDouble(E(list[0]));
               Double t2 = Convert.ToDouble(E(list[2]));

               r = t1 % t2;

               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("^") == 0)
           {
               Double t1 = Convert.ToDouble(E(list[0]));
               Double t2 = Convert.ToDouble(E(list[2]));

               r = Math.Pow(t1, t2);

               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("falso") == 0)
           {
               r = false;

               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("verdadero") == 0)
           {
               r = true;

               return r;
           }
           else if (list[0].ToString().CompareTo("num") == 0)
           {
               string[] temp =list[0].FindTokenAndGetText().Split('.');

               if (temp.Length > 1)
               {
                   r = Convert.ToDouble(temp);
               }
               else {
                   r = Convert.ToInt32(temp);
               }

               return r;
           }
           else if (list[0].ToString().CompareTo("cad") == 0)
           {
               r = list[0].FindTokenAndGetText();

               return r;
           }
           else if (list[0].ToString().CompareTo("id") == 0)
           {
               string temp = list[0].FindTokenAndGetText();
               Simbolo sim = tablaSimbolos.Find(x => x.Nombre.Contains(temp));

               r = sim.Valor;

               return r;
           }
           else if (list[0].ToString().CompareTo("caracter") == 0)
           {
               r = Convert.ToChar(list[0].FindTokenAndGetText());
               return r;
           }
           else if (list[1].ToString().CompareTo("Dims") == 0)
           {
               Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Equals(list[0].FindTokenAndGetText()));
               if (temp.TipoSim.CompareTo("arreglo") == 0)
               {
                   object[] arr = (object[])temp.Valor;
                   List<int> dimensiones = temp.Dims;
                   List<int> indice = new List<int>();
                   dims(list[1], indice);

                   int pos = indice[0] - 1;
                   if (dimensiones.Count > 1)
                   {
                       int w = 1;
                       while (w < dimensiones.Count)
                       {
                           pos = (pos * dimensiones[w]) + (indice[w] - 1);
                           w++;
                       }
                   }
                   r = arr[pos];
               }
               
               return r;
           }
           else if (list[0].ToString().CompareTo("Valor") == 0)
           {
               r = Valor(list[0]);
               return r;
           }
           else if (list[0].ToString().CompareTo("AsigSimplificada") == 0)
           {
               r = AsigSimplificada(list[0]);
               return r;
           }
           else if (list[0].ToString().CompareTo("CallMorF") == 0)
           {
               r = CallMorF(list[0]);
               return r;
           }
           else if (list[0].FindTokenAndGetText().CompareTo("!¡") == 0)
           {
               string temp = list[1].FindTokenAndGetText();
               Simbolo sim = tablaSimbolos.Find(x => x.Nombre.Contains(temp));

               object e = sim.Valor;
               if (e==null)
               {
                   r = true;
               }
               else
               {
                   r = false;
               }

               return r;
           }

           return null;
       }

       private object Valor(ParseTreeNode nodo) {
           ParseTreeNodeList list = nodo.ChildNodes;
           object r;

           if (list[1].ToString().CompareTo("Opr") == 0)
           {

           }
           else if (list[1].FindTokenAndGetText().CompareTo("||") == 0)
           {
               r = false;
               Boolean t1 = Convert.ToBoolean(E(list[0]));
               Boolean t2 = Convert.ToBoolean(E(list[2]));

               if (t1 == true)
               {
                    r = true;
               }
               else {
                   if (t2 == true)
                   {
                       r = true;
                   }
               }
               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("!||") == 0)
           {
               r = true;
               Boolean t1 = Convert.ToBoolean(E(list[0]));
               Boolean t2 = Convert.ToBoolean(E(list[2]));

               if (t1 == true)
               {
                   r = false;
               }
               else
               {
                   if (t2 == true)
                   {
                       r = false;
                   }
               }
               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("&|") == 0)
           {
               r = false;
               Boolean t1 = Convert.ToBoolean(E(list[0]));
               Boolean t2 = Convert.ToBoolean(E(list[2]));

               if (t1 == true)
               {
                   if (t2 == false) {
                       r = true;
                   }
               }
               else
               {
                   if (t2 == true)
                   {
                       r = true;
                   }
               }
               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("!&&") == 0)
           {
               r = true;
               Boolean t1 = Convert.ToBoolean(E(list[0]));
               Boolean t2 = Convert.ToBoolean(E(list[2]));

               if (t1 == true)
               {
                   if (t2 == true)
                   {
                       r = false;
                   }
               }
               return r;
           }
           else if (list[1].FindTokenAndGetText().CompareTo("&&") == 0)
           {
               r = false;
               Boolean t1 = Convert.ToBoolean(E(list[0]));
               Boolean t2 = Convert.ToBoolean(E(list[2]));

               if (t1 == true)
               {
                   if (t2 == true)
                   {
                       r = true;
                   }
               }
               return r;
           }
           else if (list[0].FindTokenAndGetText().CompareTo("!") == 0)
           {
               r = false;
               Boolean t1 = Convert.ToBoolean(E(list[0]));

               if (t1 == false)
               {
                   r = true;
               }
               return r;
           }
           else if (list[0].ToString().CompareTo("E") == 0)
           {
               r = E(list[0]);

               return r;
           }

           return null;
       }

       private object Opr(ParseTreeNode nodo,object e1, object e2) {

           ParseTreeNodeList op = nodo.ChildNodes;
           object r;
           if (op[0].FindTokenAndGetText().CompareTo("==") == 0) {
               if (e1 == e2)
               {
                  r= true;
               }
               else {
                   r= false;
               }
               return r;
           }
           else if (op[0].FindTokenAndGetText().CompareTo("<") == 0)
           {
               if (Convert.ToInt32(e1) < Convert.ToInt32(e2))
               {
                   r = true;
               }
               else
               {
                   r = false;
               }
               return r;
           }
           else if (op[0].FindTokenAndGetText().CompareTo(">") == 0)
           {
               if (Convert.ToInt32(e1) > Convert.ToInt32(e2))
               {
                   r = true;
               }
               else
               {
                   r = false;
               }
               return r;
           }
           else if (op[0].FindTokenAndGetText().CompareTo(">=") == 0)
           {
               if (Convert.ToInt32(e1) >= Convert.ToInt32(e2))
               {
                   r = true;
               }
               else
               {
                   r = false;
               }
               return r;
           }
           else if (op[0].FindTokenAndGetText().CompareTo("<=") == 0)
           {
               if (Convert.ToInt32(e1) <= Convert.ToInt32(e2))
               {
                   r = true;
               }
               else
               {
                   r = false;
               }
               return r;
           }
           else if (op[0].FindTokenAndGetText().CompareTo("!=") == 0)
           {
               if (e1 != e2)
               {
                   r = true;
               }
               else
               {
                   r = false;
               }
               return r;
           }
          
           return null;
       }

       private object CallMorF(ParseTreeNode nodo) {
           ParseTreeNodeList list = nodo.ChildNodes;
           object r = null;
           if (list[1].ToString().CompareTo("Param") == 0) {
                Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Equals(list[0].FindTokenAndGetText()));
                if (temp.TipoSim.CompareTo("metodo") == 0)
                {
                    List<Simbolo> param_decla = paramMeth(temp);
                    List<object> param_val = Param(list[1]);
                    if (param_decla.Count == param_val.Count)
                    {
                        asigValParam(param_val, temp);
                        r = EjecutarLS(temp.Morf, temp.Padre);
                        if (temp.TipoDato.CompareTo("") == 0)
                        {
                            if (r != null)
                            {
                                //error metodo void y hay return
                            }
                        }
                    }
                    else { 
                    //error le hacen falta parametros o datos incompatibles
                    }
                }
           }
           else if (list[0].ToString().CompareTo("Fun") == 0)
           {
               //metodo Fun
           }
           else {
               Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Equals(list[0].FindTokenAndGetText()));
               if (temp.TipoSim.CompareTo("metodo") == 0)
               {
                   List<Simbolo> l = paramMeth(temp);
                   if (l == null) {

                       r = EjecutarLS(temp.Morf,temp.Padre);
                       if (temp.TipoDato.CompareTo("") == 0) {
                           if (r != null) { 
                           //error metodo void y hay return
                           }
                       }
                   }
                   else { 
                   //error metodo con parametros
                   }
                 
               }
           }
           return r;
       }

       private List<Simbolo> paramMeth(Simbolo metodo) {
           List<Simbolo> l = null;
           for (int i = 0; i < tablaSimbolos.Count; i++)
           {
               Simbolo tmp = tablaSimbolos[i];
               if (tmp.TipoSim.CompareTo("parametro") == 0 && tmp.Padre.CompareTo(metodo.Nombre) == 0)
               {
                   l.Add(tmp);
               }
           }
           return l;
       }

       public void asigValParam(List<object> l, Simbolo metodo)
       {
           for (int i = 0; i < tablaSimbolos.Count; i++)
           {
               Simbolo tmp = tablaSimbolos[i];
               if (tmp.TipoSim.CompareTo("parametro") == 0 && tmp.Padre.CompareTo(metodo.Nombre) == 0)
               {
                   string tipodatos = tmp.TipoDato;
                   Type tipodatopar = l[i].GetType();

                   if(tipodatos.CompareTo("entero")==0){
                       if (tipodatopar == typeof(int))
                       {
                           tmp.Valor = l[i];
                       }
                       else { 
                       //error datos incompatibles
                       }
                   }
                   else if (tipodatos.CompareTo("boolean") == 0)
                   {
                       if (tipodatopar == typeof(bool))
                       {
                           tmp.Valor = l[i];
                       }
                       else
                       {
                           //error datos incompatibles
                       }
                   } else if (tipodatos.CompareTo("cadena") == 0)
                   {
                       if (tipodatopar == typeof(string))
                       {
                           tmp.Valor = l[i];
                       }
                       else
                       {
                           //error datos incompatibles
                       }
                   } else if (tipodatos.CompareTo("double") == 0)
                   {
                       if (tipodatopar == typeof(double))
                       {
                           tmp.Valor = l[i];
                       }
                       else
                       {
                           //error datos incompatibles
                       }
                   } if (tipodatos.CompareTo("caracter") == 0)
                   {
                       if (tipodatopar == typeof(char))
                       {
                           tmp.Valor = l[i];
                       }
                       else
                       {
                           //error datos incompatibles
                       }
                   }
                   
               }
           }

       }

       private List<Object> Param(ParseTreeNode nodo) {
           List<object> l=null;
           
           recursivoParam(nodo, l);
           
           return l;
       }

       private void recursivoParam(ParseTreeNode nodo, List<object> l) {
           ParseTreeNodeList list = nodo.ChildNodes;

           if (list.Count == 2)
           {
               recursivoParam(list[0], l);
               object val = Valor(list[1]);
               l.Add(val);
           }
           else
           {
               object val = Valor(list[0]);
               l.Add(val);
           }
       }

       private object Fun(ParseTreeNode nodo) {
           ParseTreeNodeList list = nodo.ChildNodes;
           object r=null;
           if (list[0].FindTokenAndGetText().CompareTo("Reproducir") == 0) {
               ParseTreeNodeList hijonm = list[1].ChildNodes;

               String nota = hijonm[0].FindTokenAndGetText();
               int octava = Convert.ToInt32(E(list[2]));
               int miliseg = Convert.ToInt32(E(list[3]));
               int canal = Convert.ToInt32(E(list[4]));

               r = miliseg;

           }
           else if (list[0].FindTokenAndGetText().CompareTo("Esperar") == 0) {
               int miliseg = Convert.ToInt32(E(list[3]));
               int canal = Convert.ToInt32(E(list[4]));
           }
           else if (list[0].FindTokenAndGetText().CompareTo("Ordenar") == 0) {
               r = 0;
            Simbolo temp = tablaSimbolos.Find(x => x.Nombre.Equals(list[1].FindTokenAndGetText()));
            if (temp.TipoSim.CompareTo("arreglo") == 0)
            {
                object[] arr = (object[])temp.Valor;

                ParseTreeNodeList hijonm = list[2].ChildNodes;
                if (hijonm[0].FindTokenAndGetText().CompareTo("ascendente") == 0) {
                }
                else if (hijonm[0].FindTokenAndGetText().CompareTo("descendente") == 0)
                {
                }
                else if (hijonm[0].FindTokenAndGetText().CompareTo("impares") == 0)
                {
                }
                else if (hijonm[0].FindTokenAndGetText().CompareTo("pares") == 0)
                {
                }
                else if (hijonm[0].FindTokenAndGetText().CompareTo("primos") == 0)
                {
                }
            }
           }
           else if (list[0].FindTokenAndGetText().CompareTo("Sumarizar") == 0) { }
           else if (list[0].FindTokenAndGetText().CompareTo("Longitud") == 0) { }
           else if (list[0].FindTokenAndGetText().CompareTo("Mensaje") == 0) { }

           return r;
       }

       private void If_(ParseTreeNode nodo, string padre) {
           ParseTreeNodeList list = nodo.ChildNodes;
           if (list.Count == 5)
           {
               //if else
               bool cond = Convert.ToBoolean(Valor(list[1]));
               if (cond)
               {
                   EjecutarLS(list[2], padre);
               }
               else {
                   EjecutarLS(list[4], padre);
               }
           }
           else { 
              //if
               bool cond = Convert.ToBoolean(Valor(list[1]));
               if (cond)
               {
                   EjecutarLS(list[2], padre);
               }
           }
       }

       private void While_(ParseTreeNode nodo, String padre) {
           ParseTreeNodeList list = nodo.ChildNodes;
           if (list.Count == 3)
           {
               bool cond = Convert.ToBoolean(Valor(list[1]));

               while (cond)
               {
                   EjecutarLS(list[2], padre);
                   cond = Convert.ToBoolean(Valor(list[1]));
               }
           }
       }

       private void doWhile_(ParseTreeNode nodo, string padre) {
           ParseTreeNodeList list = nodo.ChildNodes;
           if (list.Count == 4)
           {
               bool cond = Convert.ToBoolean(Valor(list[3]));

               do {
                   EjecutarLS(list[1], padre);
                   cond = Convert.ToBoolean(Valor(list[3]));
               }while (cond);     
           }
       }

       private void For_(ParseTreeNode nodo, string padre) {

           ParseTreeNodeList list = nodo.ChildNodes;

           Asignacion(list[1]);
           Boolean limite = Convert.ToBoolean(list[2]);

           while (limite) {
               EjecutarLS(list[4],padre);
               AsigSimplificada(list[3]);
               limite = Convert.ToBoolean(list[2]);
           }
       }

       private void Switch_(ParseTreeNode nodo, string padre){
           ParseTreeNodeList list = nodo.ChildNodes;

           object num = list[1];
           Dictionary<object, ParseTreeNode> lcase = new Dictionary<object, ParseTreeNode>();
          
           LCase(list[2], lcase);
           if (list.Count == 5) {
               lcase.Add(1993, list[4]);
           }
               if (lcase.ContainsKey(Convert.ToString(num)))
               { 
                  ParseTreeNode lseject = lcase[Convert.ToString(num)];
                   EjecutarLS(lseject, padre);
               }
       }

       public void LCase(ParseTreeNode nodo, Dictionary<object, ParseTreeNode> dic){
           ParseTreeNodeList list = nodo.ChildNodes;
           if (list.Count == 2)
           {
               LCase(list[0], dic);
               case_(list[1], dic);
           }
           else 
           {
               case_(list[1], dic);
           }
       }

       public void case_(ParseTreeNode nodo, Dictionary<object, ParseTreeNode> listcase) {
            ParseTreeNodeList list = nodo.ChildNodes;

            object nume = list[1];
            listcase.Add(nume, list[2]);
       }

       private object EjecutarLS(ParseTreeNode nodo, string padre) {
           object a = null;
           a = LS(nodo, padre);
           return a;
       
       }

       private void Cabecera(ParseTreeNode nodo, Pista objeto) {
           ParseTreeNodeList lista = nodo.ChildNodes;
           if (lista.Count > 2) {
           //contiene extiende
               ParseTreeNode nombre = lista[1];//nombre
               ParseTreeNode Lextiende = lista[3];
               objeto.Nombre = nombre.FindTokenAndGetText();

               Simbolo nom = new Simbolo(contid, objeto.Nombre,"pista","","","global","",false);
               contid++;
               tablaSimbolos.Add(nom);

               List<String> lista_padres=extiende(Lextiende);
               String texto="La pista " + objeto.Nombre + " Hereda de:"+"\n";
               int i = 1;
               foreach (String padre in lista_padres) {
                  texto+="\t"+i + ")";
                  texto += padre + "\n";
               }
               MessageBox.Show(texto);
               System.Console.WriteLine(texto);
               System.Console.WriteLine("----------------------");
           }

           if (lista.Count == 2) { 
              ParseTreeNode nombre = lista[1];//nombre
              
               objeto.Nombre = nombre.FindTokenAndGetText();
           }
           System.Console.WriteLine("El nombre de la pista es: "+objeto.Nombre);
       }

       private List<String> extiende(ParseTreeNode nodo) {
           List<String> lista = new List<string>();
           extiende_recursiva(nodo, lista);

           return lista;
       }

       private void extiende_recursiva(ParseTreeNode nodo,List<String> x)
       {
           if (nodo.ChildNodes.Count >= 2) {
               ParseTreeNode extiende = nodo.ChildNodes[0];
               extiende_recursiva(extiende, x);
               ParseTreeNode pista_padre = nodo.ChildNodes[1];
               x.Add(pista_padre.FindTokenAndGetText());
           }
           if (nodo.ChildNodes.Count == 1)
           {
               
               ParseTreeNode pista_padre = nodo.ChildNodes[0];
               x.Add(pista_padre.FindTokenAndGetText());
           }
          
       }

    }
}